﻿package com.adobe.utils
{
    import com.gengine.gc.*;
    import flash.utils.*;

    public class AGALMiniAssembler extends Object
    {
        protected var _agalcode:ByteArray = null;
        protected var _error:String = "";
        protected var debugEnabled:Boolean = false;
        public var verbose:Boolean = false;
        public var hasFinish:Boolean = false;
        private var _lines:Array;
        private var nops:int = 0;
        private var version:int;
        public var source:String;
        private var isFrag:Boolean;
        static const REGEXP_OUTER_SPACES:RegExp = /^\s+|\s+$""^\s+|\s+$/g;
        private static const regsReg:RegExp = /vc\[([vof][acostdip]?)(\d*)?(\.[xyzw](\+\d{1,3})?)?\](\.[xyzw]{1,4})?|([vof][acostdip]?)(\d*)?(\.[xyzw]{1,4})?""vc\[([vof][acostdip]?)(\d*)?(\.[xyzw](\+\d{1,3})?)?\](\.[xyzw]{1,4})?|([vof][acostdip]?)(\d*)?(\.[xyzw]{1,4})?/gi;
        private static const reg0:RegExp = /\[.*\]""\[.*\]/ig;
        private static const reg1:RegExp = /^\b[A-Za-z]{1,2}""^\b[A-Za-z]{1,2}/ig;
        private static const reg2:RegExp = /\d+""\d+/;
        private static const reg3:RegExp = /(\.[xyzw]{1,4})""(\.[xyzw]{1,4})/;
        private static const reg4:RegExp = /[A-Za-z]{1,2}""[A-Za-z]{1,2}/ig;
        private static const reg5:RegExp = /(\.[xyzw]{1,1})""(\.[xyzw]{1,1})/;
        private static const reg6:RegExp = /\+\d{1,3}""\+\d{1,3}/ig;
        private static const reg7:RegExp = /[\f\
n\r\v]+""[\f\n\r\v]+/g;
        private static const reg8:RegExp = /<.*>""<.*>/g;
        private static const reg9:RegExp = /([\w\.\-\+]+)""([\w\.\-\+]+)/gi;
        private static const reg10:RegExp = /^\w{3}""^\w{3}/ig;
        private static const xChar0:Number = "x".charCodeAt(0);
        private static const constValue:Number = 1 << 15;
        static var initialized:Boolean = false;
        static const OPMAP:Dictionary = new Dictionary();
        static const REGMAP:Dictionary = new Dictionary();
        static const SAMPLEMAP:Dictionary = new Dictionary();
        static const MAX_OPCODES:int = 2048;
        static const FRAGMENT:String = "fragment";
        static const VERTEX:String = "vertex";
        static const SAMPLER_TYPE_SHIFT:uint = 8;
        static const SAMPLER_DIM_SHIFT:uint = 12;
        static const SAMPLER_SPECIAL_SHIFT:uint = 16;
        static const SAMPLER_REPEAT_SHIFT:uint = 20;
        static const SAMPLER_MIPMAP_SHIFT:uint = 24;
        static const SAMPLER_FILTER_SHIFT:uint = 28;
        static const REG_WRITE:uint = 1;
        static const REG_READ:uint = 2;
        static const REG_FRAG:uint = 32;
        static const REG_VERT:uint = 64;
        static const OP_SCALAR:uint = 1;
        static const OP_SPECIAL_TEX:uint = 8;
        static const OP_SPECIAL_MATRIX:uint = 16;
        static const OP_FRAG_ONLY:uint = 32;
        static const OP_VERT_ONLY:uint = 64;
        static const OP_NO_DEST:uint = 128;
        static const OP_VERSION2:uint = 256;
        static const OP_INCNEST:uint = 512;
        static const OP_DECNEST:uint = 1024;
        static const MOV:String = "mov";
        static const ADD:String = "add";
        static const SUB:String = "sub";
        static const MUL:String = "mul";
        static const DIV:String = "div";
        static const RCP:String = "rcp";
        static const MIN:String = "min";
        static const MAX:String = "max";
        static const FRC:String = "frc";
        static const SQT:String = "sqt";
        static const RSQ:String = "rsq";
        static const POW:String = "pow";
        static const LOG:String = "log";
        static const EXP:String = "exp";
        static const NRM:String = "nrm";
        static const SIN:String = "sin";
        static const COS:String = "cos";
        static const CRS:String = "crs";
        static const DP3:String = "dp3";
        static const DP4:String = "dp4";
        static const ABS:String = "abs";
        static const NEG:String = "neg";
        static const SAT:String = "sat";
        static const M33:String = "m33";
        static const M44:String = "m44";
        static const M34:String = "m34";
        static const DDX:String = "ddx";
        static const DDY:String = "ddy";
        static const IFE:String = "ife";
        static const INE:String = "ine";
        static const IFG:String = "ifg";
        static const IFL:String = "ifl";
        static const ELS:String = "els";
        static const EIF:String = "eif";
        static const TED:String = "ted";
        static const KIL:String = "kil";
        static const TEX:String = "tex";
        static const SGE:String = "sge";
        static const SLT:String = "slt";
        static const SGN:String = "sgn";
        static const SEQ:String = "seq";
        static const SNE:String = "sne";
        static const VA:String = "va";
        static const VC:String = "vc";
        static const VT:String = "vt";
        static const VO:String = "vo";
        static const VI:String = "vi";
        static const FC:String = "fc";
        static const FT:String = "ft";
        static const FS:String = "fs";
        static const FO:String = "fo";
        static const FD:String = "fd";
        static const D2:String = "2d";
        static const D3:String = "3d";
        static const CUBE:String = "cube";
        static const MIPNEAREST:String = "mipnearest";
        static const MIPLINEAR:String = "miplinear";
        static const MIPNONE:String = "mipnone";
        static const NOMIP:String = "nomip";
        static const NEAREST:String = "nearest";
        static const LINEAR:String = "linear";
        static const CENTROID:String = "centroid";
        static const SINGLE:String = "single";
        static const IGNORESAMPLER:String = "ignoresampler";
        static const REPEAT:String = "repeat";
        static const WRAP:String = "wrap";
        static const CLAMP:String = "clamp";
        static const RGBA:String = "rgba";
        static const DXT1:String = "dxt1";
        static const DXT5:String = "dxt5";
        static const VIDEO:String = "video";

        public function AGALMiniAssembler(param1:Boolean = false) : void
        {
            this.debugEnabled = param1;
            if (!initialized)
            {
                init();
            }
            return;
        }// end function

        public function get error() : String
        {
            return this._error;
        }// end function

        public function get agalcode() : ByteArray
        {
            return this._agalcode;
        }// end function

        public function goOn(param1:Boolean, param2:Number) : void
        {
            var _loc_3:String = null;
            var _loc_4:String = null;
            var _loc_5:int = 0;
            var _loc_6:int = 0;
            var _loc_7:Array = null;
            var _loc_8:Array = null;
            var _loc_9:OpCode = null;
            var _loc_10:Array = null;
            var _loc_11:Boolean = false;
            while (this._lines.length > 0 && (!param1 || getTimer() - param2 < 20))
            {
                
                var _loc_12:String = this;
                var _loc_13:* = this.nops + 1;
                _loc_12.nops = _loc_13;
                if (this.nops > MAX_OPCODES)
                {
                    this._error = "error: too many opcodes. maximum is " + MAX_OPCODES + ".";
                    break;
                }
                _loc_3 = this._lines.shift();
                _loc_4 = _loc_3.replace(REGEXP_OUTER_SPACES, "");
                _loc_5 = _loc_4.search("//");
                if (_loc_5 != -1)
                {
                    _loc_4 = _loc_4.slice(0, _loc_5);
                }
                _loc_6 = _loc_4.search(reg8);
                if (_loc_6 != -1)
                {
                    _loc_7 = _loc_4.slice(_loc_6).match(reg9);
                    _loc_4 = _loc_4.slice(0, _loc_6);
                }
                _loc_8 = _loc_4.match(reg10);
                if (!_loc_8)
                {
                    if (_loc_4.length >= 3)
                    {
                        trace("warning: bad line " + this.nops + ": " + _loc_3);
                    }
                    continue;
                }
                _loc_9 = OPMAP[_loc_8[0]];
                if (this.debugEnabled)
                {
                    trace(_loc_9);
                }
                if (_loc_9 == null)
                {
                    if (_loc_4.length >= 3)
                    {
                        trace("warning: bad line " + this.nops + ": " + _loc_3);
                    }
                    continue;
                }
                _loc_4 = _loc_4.slice(_loc_4.search(_loc_9.name) + _loc_9.name.length);
                if (_loc_9.flags & OP_VERSION2 && this.version < 2)
                {
                    this._error = "error: opcode requires version 2.";
                    break;
                }
                if (_loc_9.flags & OP_VERT_ONLY && this.isFrag)
                {
                    this._error = "error: opcode is only allowed in vertex programs.";
                    break;
                }
                if (_loc_9.flags & OP_FRAG_ONLY && !this.isFrag)
                {
                    this._error = "error: opcode is only allowed in fragment programs.";
                    break;
                }
                if (this.verbose)
                {
                    trace("emit opcode=" + _loc_9);
                }
                this._agalcode.writeUnsignedInt(_loc_9.emitCode);
                _loc_10 = _loc_4.match(regsReg);
                if (!_loc_10 || _loc_10.length != _loc_9.numRegister)
                {
                    this._error = "error: wrong number of operands. found " + _loc_10.length + " but expected " + _loc_9.numRegister + ".";
                    break;
                }
                _loc_11 = this.assemblerLine(_loc_10, _loc_9, _loc_7);
                if (!_loc_11)
                {
                    break;
                }
            }
            if (this._error == "" && this._lines.length == 0)
            {
                this.hasFinish = true;
            }
            else
            {
                if (this._error != "")
                {
                    this._agalcode.length = 0;
                    trace("error in AGALMiniAssembler : " + _loc_3 + "\nerror:" + this._error);
                    throw new AGALEvent(this._error);
                }
                this.hasFinish = false;
            }
            return;
        }// end function

        private function assemblerLine(param1:Array, param2:OpCode, param3:Array) : Boolean
        {
            var _loc_8:Boolean = false;
            var _loc_9:Array = null;
            var _loc_10:Array = null;
            var _loc_11:Register = null;
            var _loc_12:Array = null;
            var _loc_13:uint = 0;
            var _loc_14:uint = 0;
            var _loc_15:Array = null;
            var _loc_16:Boolean = false;
            var _loc_17:Boolean = false;
            var _loc_18:uint = 0;
            var _loc_19:uint = 0;
            var _loc_20:int = 0;
            var _loc_21:uint = 0;
            var _loc_22:uint = 0;
            var _loc_23:int = 0;
            var _loc_24:Array = null;
            var _loc_25:Register = null;
            var _loc_26:Array = null;
            var _loc_27:Array = null;
            var _loc_28:uint = 0;
            var _loc_29:uint = 0;
            var _loc_30:Number = NaN;
            var _loc_31:Sampler = null;
            var _loc_4:Boolean = false;
            var _loc_5:* = 64 + 64 + 32;
            var _loc_6:* = param1.length;
            var _loc_7:int = 0;
            while (_loc_7 < _loc_6)
            {
                
                _loc_8 = false;
                _loc_9 = param1[_loc_7].match(reg0);
                if (_loc_9 && _loc_9.length > 0)
                {
                    param1[_loc_7] = param1[_loc_7].replace(_loc_9[0], "0");
                    if (this.verbose)
                    {
                        trace("IS REL");
                    }
                    _loc_8 = true;
                }
                _loc_10 = param1[_loc_7].match(reg1);
                if (!_loc_10)
                {
                    this._error = "error: could not parse operand " + _loc_7 + " (" + param1[_loc_7] + ").";
                    _loc_4 = true;
                    break;
                }
                _loc_11 = REGMAP[_loc_10[0]];
                if (this.debugEnabled)
                {
                    trace(_loc_11);
                }
                if (_loc_11 == null)
                {
                    this._error = "error: could not find register name for operand " + _loc_7 + " (" + param1[_loc_7] + ").";
                    _loc_4 = true;
                    break;
                }
                if (this.isFrag)
                {
                    if (!(_loc_11.flags & REG_FRAG))
                    {
                        this._error = "error: register operand " + _loc_7 + " (" + param1[_loc_7] + ") only allowed in vertex programs.";
                        _loc_4 = true;
                        break;
                    }
                    if (_loc_8)
                    {
                        this._error = "error: register operand " + _loc_7 + " (" + param1[_loc_7] + ") relative adressing not allowed in fragment programs.";
                        _loc_4 = true;
                        break;
                    }
                }
                else if (!(_loc_11.flags & REG_VERT))
                {
                    this._error = "error: register operand " + _loc_7 + " (" + param1[_loc_7] + ") only allowed in fragment programs.";
                    _loc_4 = true;
                    break;
                }
                param1[_loc_7] = param1[_loc_7].slice(param1[_loc_7].search(_loc_11.name) + _loc_11.name.length);
                _loc_12 = _loc_8 ? (_loc_9[0].match(reg2)) : (param1[_loc_7].match(reg2));
                _loc_13 = 0;
                if (_loc_12)
                {
                    _loc_13 = uint(_loc_12[0]);
                }
                if (_loc_11.range < _loc_13)
                {
                    this._error = "error: register operand " + _loc_7 + " (" + param1[_loc_7] + ") index exceeds limit of " + (_loc_11.range + 1) + ".";
                    _loc_4 = true;
                    break;
                }
                _loc_14 = 0;
                _loc_15 = param1[_loc_7].match(reg3);
                _loc_16 = _loc_7 == 0 && !(param2.flags & OP_NO_DEST);
                _loc_17 = _loc_7 == 2 && param2.flags & OP_SPECIAL_TEX;
                _loc_18 = 0;
                _loc_19 = 0;
                _loc_20 = 0;
                if (_loc_16 && _loc_8)
                {
                    this._error = "error: relative can not be destination";
                    _loc_4 = true;
                    break;
                }
                if (_loc_15)
                {
                    _loc_14 = 0;
                    _loc_22 = _loc_15[0].length;
                    _loc_23 = 1;
                    while (_loc_23 < _loc_22)
                    {
                        
                        _loc_21 = _loc_15[0].charCodeAt(_loc_23) - xChar0;
                        if (_loc_21 > 2)
                        {
                            _loc_21 = 3;
                        }
                        if (_loc_16)
                        {
                            _loc_14 = _loc_14 | 1 << _loc_21;
                        }
                        else
                        {
                            _loc_14 = _loc_14 | _loc_21 << ((_loc_23 - 1) << 1);
                        }
                        _loc_23++;
                    }
                    if (!_loc_16)
                    {
                        while (_loc_23 <= 4)
                        {
                            
                            _loc_14 = _loc_14 | _loc_21 << ((_loc_23 - 1) << 1);
                            _loc_23++;
                        }
                    }
                }
                else
                {
                    _loc_14 = _loc_16 ? (15) : (228);
                }
                if (_loc_8)
                {
                    _loc_24 = _loc_9[0].match(reg4);
                    _loc_25 = REGMAP[_loc_24[0]];
                    if (_loc_25 == null)
                    {
                        this._error = "error: bad index register";
                        _loc_4 = true;
                        break;
                    }
                    _loc_18 = _loc_25.emitCode;
                    _loc_26 = _loc_9[0].match(reg5);
                    if (_loc_26.length == 0)
                    {
                        this._error = "error: bad index register select";
                        _loc_4 = true;
                        break;
                    }
                    _loc_19 = _loc_26[0].charCodeAt(1) - xChar0;
                    if (_loc_19 > 2)
                    {
                        _loc_19 = 3;
                    }
                    _loc_27 = _loc_9[0].match(reg6);
                    if (_loc_27.length > 0)
                    {
                        _loc_20 = _loc_27[0];
                    }
                    if (_loc_20 < 0 || _loc_20 > 255)
                    {
                        this._error = "error: index offset " + _loc_20 + " out of bounds. [0..255]";
                        _loc_4 = true;
                        break;
                    }
                    if (this.verbose)
                    {
                        trace("RELATIVE: type=" + _loc_18 + "==" + _loc_24[0] + " sel=" + _loc_19 + "==" + _loc_26[0] + " idx=" + _loc_13 + " offset=" + _loc_20);
                    }
                }
                if (this.verbose)
                {
                    trace("  emit argcode=" + _loc_11 + "[" + _loc_13 + "][" + _loc_14 + "]");
                }
                if (_loc_16)
                {
                    this._agalcode.writeShort(_loc_13);
                    this._agalcode.writeByte(_loc_14);
                    this._agalcode.writeByte(_loc_11.emitCode);
                    _loc_5 = _loc_5 - 32;
                }
                else if (_loc_17)
                {
                    if (this.verbose)
                    {
                        trace("  emit sampler");
                    }
                    _loc_28 = 5;
                    _loc_29 = param3 == null ? (0) : (param3.length);
                    _loc_30 = 0;
                    _loc_23 = 0;
                    while (_loc_23 < _loc_29)
                    {
                        
                        if (this.verbose)
                        {
                            trace("    opt: " + param3[_loc_23]);
                        }
                        _loc_31 = SAMPLEMAP[param3[_loc_23]];
                        if (_loc_31 == null)
                        {
                            _loc_30 = Number(param3[_loc_23]);
                            if (this.verbose)
                            {
                                trace("    bias: " + _loc_30);
                            }
                        }
                        else
                        {
                            if (_loc_31.flag != SAMPLER_SPECIAL_SHIFT)
                            {
                                _loc_28 = _loc_28 & ~(15 << _loc_31.flag);
                            }
                            _loc_28 = _loc_28 | uint(_loc_31.mask) << uint(_loc_31.flag);
                        }
                        _loc_23++;
                    }
                    this._agalcode.writeShort(_loc_13);
                    this._agalcode.writeByte(int(_loc_30 * 8));
                    this._agalcode.writeByte(0);
                    this._agalcode.writeUnsignedInt(_loc_28);
                    if (this.verbose)
                    {
                        trace("    bits: " + (_loc_28 - 5));
                    }
                    _loc_5 = _loc_5 - 64;
                }
                else
                {
                    if (_loc_7 == 0)
                    {
                        this._agalcode.writeUnsignedInt(0);
                        _loc_5 = _loc_5 - 32;
                    }
                    this._agalcode.writeShort(_loc_13);
                    this._agalcode.writeByte(_loc_20);
                    this._agalcode.writeByte(_loc_14);
                    this._agalcode.writeByte(_loc_11.emitCode);
                    this._agalcode.writeByte(_loc_18);
                    this._agalcode.writeShort(_loc_8 ? (_loc_19 | constValue) : (0));
                    _loc_5 = _loc_5 - 64;
                }
                _loc_7++;
            }
            _loc_7 = 0;
            while (_loc_7 < _loc_5)
            {
                
                this._agalcode.writeByte(0);
                _loc_7 = _loc_7 + 8;
            }
            return !_loc_4;
        }// end function

        public function assemble(param1:String, param2:String, param3:uint = 1, param4:Boolean = false) : void
        {
            this.source = param2;
            this.version = param3;
            this._agalcode = new GByteArray();
            this._error = "";
            this.isFrag = false;
            if (param1 == FRAGMENT)
            {
                this.isFrag = true;
            }
            else if (param1 != VERTEX)
            {
                this._error = "ERROR: mode needs to be \"" + FRAGMENT + "\" or \"" + VERTEX + "\" but is \"" + param1 + "\".";
            }
            this._agalcode.endian = Endian.LITTLE_ENDIAN;
            this._agalcode.writeByte(160);
            this._agalcode.writeUnsignedInt(this.version);
            this._agalcode.writeByte(161);
            this._agalcode.writeByte(this.isFrag ? (1) : (0));
            this.initregmap(this.version, param4);
            this._lines = this.source.replace(reg7, "\n").split("\n");
            this.nops = 0;
            return;
        }// end function

        protected function initregmap(param1:uint, param2:Boolean) : void
        {
            REGMAP[VA] = new Register(VA, "vertex attribute", 0, param2 ? (1024) : (7), REG_VERT | REG_READ);
            REGMAP[VC] = new Register(VC, "vertex constant", 1, param2 ? (1024) : (param1 == 1 ? (127) : (250)), REG_VERT | REG_READ);
            REGMAP[VT] = new Register(VT, "vertex temporary", 2, param2 ? (1024) : (param1 == 1 ? (7) : (27)), REG_VERT | REG_WRITE | REG_READ);
            REGMAP[VO] = new Register(VO, "vertex output", 3, param2 ? (1024) : (0), REG_VERT | REG_WRITE);
            REGMAP[VI] = new Register(VI, "varying", 4, param2 ? (1024) : (param1 == 1 ? (7) : (11)), REG_VERT | REG_FRAG | REG_READ | REG_WRITE);
            REGMAP[FC] = new Register(FC, "fragment constant", 1, param2 ? (1024) : (param1 == 1 ? (27) : (63)), REG_FRAG | REG_READ);
            REGMAP[FT] = new Register(FT, "fragment temporary", 2, param2 ? (1024) : (param1 == 1 ? (7) : (27)), REG_FRAG | REG_WRITE | REG_READ);
            REGMAP[FS] = new Register(FS, "texture sampler", 5, param2 ? (1024) : (7), REG_FRAG | REG_READ);
            REGMAP[FO] = new Register(FO, "fragment output", 3, param2 ? (1024) : (param1 == 1 ? (0) : (3)), REG_FRAG | REG_WRITE);
            REGMAP[FD] = new Register(FD, "fragment depth output", 6, param2 ? (1024) : (param1 == 1 ? (-1) : (0)), REG_FRAG | REG_WRITE);
            REGMAP["op"] = REGMAP[VO];
            REGMAP["i"] = REGMAP[VI];
            REGMAP["v"] = REGMAP[VI];
            REGMAP["oc"] = REGMAP[FO];
            REGMAP["od"] = REGMAP[FD];
            REGMAP["fi"] = REGMAP[VI];
            return;
        }// end function

        static function init() : void
        {
            initialized = true;
            OPMAP[MOV] = new OpCode(MOV, 2, 0, 0);
            OPMAP[ADD] = new OpCode(ADD, 3, 1, 0);
            OPMAP[SUB] = new OpCode(SUB, 3, 2, 0);
            OPMAP[MUL] = new OpCode(MUL, 3, 3, 0);
            OPMAP[DIV] = new OpCode(DIV, 3, 4, 0);
            OPMAP[RCP] = new OpCode(RCP, 2, 5, 0);
            OPMAP[MIN] = new OpCode(MIN, 3, 6, 0);
            OPMAP[MAX] = new OpCode(MAX, 3, 7, 0);
            OPMAP[FRC] = new OpCode(FRC, 2, 8, 0);
            OPMAP[SQT] = new OpCode(SQT, 2, 9, 0);
            OPMAP[RSQ] = new OpCode(RSQ, 2, 10, 0);
            OPMAP[POW] = new OpCode(POW, 3, 11, 0);
            OPMAP[LOG] = new OpCode(LOG, 2, 12, 0);
            OPMAP[EXP] = new OpCode(EXP, 2, 13, 0);
            OPMAP[NRM] = new OpCode(NRM, 2, 14, 0);
            OPMAP[SIN] = new OpCode(SIN, 2, 15, 0);
            OPMAP[COS] = new OpCode(COS, 2, 16, 0);
            OPMAP[CRS] = new OpCode(CRS, 3, 17, 0);
            OPMAP[DP3] = new OpCode(DP3, 3, 18, 0);
            OPMAP[DP4] = new OpCode(DP4, 3, 19, 0);
            OPMAP[ABS] = new OpCode(ABS, 2, 20, 0);
            OPMAP[NEG] = new OpCode(NEG, 2, 21, 0);
            OPMAP[SAT] = new OpCode(SAT, 2, 22, 0);
            OPMAP[M33] = new OpCode(M33, 3, 23, OP_SPECIAL_MATRIX);
            OPMAP[M44] = new OpCode(M44, 3, 24, OP_SPECIAL_MATRIX);
            OPMAP[M34] = new OpCode(M34, 3, 25, OP_SPECIAL_MATRIX);
            OPMAP[DDX] = new OpCode(DDX, 2, 26, OP_VERSION2 | OP_FRAG_ONLY);
            OPMAP[DDY] = new OpCode(DDY, 2, 27, OP_VERSION2 | OP_FRAG_ONLY);
            OPMAP[IFE] = new OpCode(IFE, 2, 28, OP_NO_DEST | OP_VERSION2 | OP_INCNEST | OP_SCALAR);
            OPMAP[INE] = new OpCode(INE, 2, 29, OP_NO_DEST | OP_VERSION2 | OP_INCNEST | OP_SCALAR);
            OPMAP[IFG] = new OpCode(IFG, 2, 30, OP_NO_DEST | OP_VERSION2 | OP_INCNEST | OP_SCALAR);
            OPMAP[IFL] = new OpCode(IFL, 2, 31, OP_NO_DEST | OP_VERSION2 | OP_INCNEST | OP_SCALAR);
            OPMAP[ELS] = new OpCode(ELS, 0, 32, OP_NO_DEST | OP_VERSION2 | OP_INCNEST | OP_DECNEST | OP_SCALAR);
            OPMAP[EIF] = new OpCode(EIF, 0, 33, OP_NO_DEST | OP_VERSION2 | OP_DECNEST | OP_SCALAR);
            OPMAP[TED] = new OpCode(TED, 3, 38, OP_FRAG_ONLY | OP_SPECIAL_TEX | OP_VERSION2);
            OPMAP[KIL] = new OpCode(KIL, 1, 39, OP_NO_DEST | OP_FRAG_ONLY);
            OPMAP[TEX] = new OpCode(TEX, 3, 40, OP_FRAG_ONLY | OP_SPECIAL_TEX);
            OPMAP[SGE] = new OpCode(SGE, 3, 41, 0);
            OPMAP[SLT] = new OpCode(SLT, 3, 42, 0);
            OPMAP[SGN] = new OpCode(SGN, 2, 43, 0);
            OPMAP[SEQ] = new OpCode(SEQ, 3, 44, 0);
            OPMAP[SNE] = new OpCode(SNE, 3, 45, 0);
            SAMPLEMAP[RGBA] = new Sampler(RGBA, SAMPLER_TYPE_SHIFT, 0);
            SAMPLEMAP[DXT1] = new Sampler(DXT1, SAMPLER_TYPE_SHIFT, 1);
            SAMPLEMAP[DXT5] = new Sampler(DXT5, SAMPLER_TYPE_SHIFT, 2);
            SAMPLEMAP[VIDEO] = new Sampler(VIDEO, SAMPLER_TYPE_SHIFT, 3);
            SAMPLEMAP[D2] = new Sampler(D2, SAMPLER_DIM_SHIFT, 0);
            SAMPLEMAP[D3] = new Sampler(D3, SAMPLER_DIM_SHIFT, 2);
            SAMPLEMAP[CUBE] = new Sampler(CUBE, SAMPLER_DIM_SHIFT, 1);
            SAMPLEMAP[MIPNEAREST] = new Sampler(MIPNEAREST, SAMPLER_MIPMAP_SHIFT, 1);
            SAMPLEMAP[MIPLINEAR] = new Sampler(MIPLINEAR, SAMPLER_MIPMAP_SHIFT, 2);
            SAMPLEMAP[MIPNONE] = new Sampler(MIPNONE, SAMPLER_MIPMAP_SHIFT, 0);
            SAMPLEMAP[NOMIP] = new Sampler(NOMIP, SAMPLER_MIPMAP_SHIFT, 0);
            SAMPLEMAP[NEAREST] = new Sampler(NEAREST, SAMPLER_FILTER_SHIFT, 0);
            SAMPLEMAP[LINEAR] = new Sampler(LINEAR, SAMPLER_FILTER_SHIFT, 1);
            SAMPLEMAP[CENTROID] = new Sampler(CENTROID, SAMPLER_SPECIAL_SHIFT, 1 << 0);
            SAMPLEMAP[SINGLE] = new Sampler(SINGLE, SAMPLER_SPECIAL_SHIFT, 1 << 1);
            SAMPLEMAP[IGNORESAMPLER] = new Sampler(IGNORESAMPLER, SAMPLER_SPECIAL_SHIFT, 1 << 2);
            SAMPLEMAP[REPEAT] = new Sampler(REPEAT, SAMPLER_REPEAT_SHIFT, 1);
            SAMPLEMAP[WRAP] = new Sampler(WRAP, SAMPLER_REPEAT_SHIFT, 1);
            SAMPLEMAP[CLAMP] = new Sampler(CLAMP, SAMPLER_REPEAT_SHIFT, 0);
            return;
        }// end function

    }
}

class OpCode extends Object
{
    protected var _emitCode:uint;
    protected var _flags:uint;
    protected var _name:String;
    protected var _numRegister:uint;

    function OpCode(param1:String, param2:uint, param3:uint, param4:uint)
    {
        this._name = param1;
        this._numRegister = param2;
        this._emitCode = param3;
        this._flags = param4;
        return;
    }// end function

    public function get emitCode() : uint
    {
        return this._emitCode;
    }// end function

    public function get flags() : uint
    {
        return this._flags;
    }// end function

    public function get name() : String
    {
        return this._name;
    }// end function

    public function get numRegister() : uint
    {
        return this._numRegister;
    }// end function

    public function toString() : String
    {
        return "[OpCode name=\"" + this._name + "\", numRegister=" + this._numRegister + ", emitCode=" + this._emitCode + ", flags=" + this._flags + "]";
    }// end function

}


class Register extends Object
{
    protected var _emitCode:uint;
    protected var _name:String;
    protected var _longName:String;
    protected var _flags:uint;
    protected var _range:uint;

    function Register(param1:String, param2:String, param3:uint, param4:uint, param5:uint)
    {
        this._name = param1;
        this._longName = param2;
        this._emitCode = param3;
        this._range = param4;
        this._flags = param5;
        return;
    }// end function

    public function get emitCode() : uint
    {
        return this._emitCode;
    }// end function

    public function get longName() : String
    {
        return this._longName;
    }// end function

    public function get name() : String
    {
        return this._name;
    }// end function

    public function get flags() : uint
    {
        return this._flags;
    }// end function

    public function get range() : uint
    {
        return this._range;
    }// end function

    public function toString() : String
    {
        return "[Register name=\"" + this._name + "\", longName=\"" + this._longName + "\", emitCode=" + this._emitCode + ", range=" + this._range + ", flags=" + this._flags + "]";
    }// end function

}


class Sampler extends Object
{
    protected var _flag:uint;
    protected var _mask:uint;
    protected var _name:String;

    function Sampler(param1:String, param2:uint, param3:uint)
    {
        this._name = param1;
        this._flag = param2;
        this._mask = param3;
        return;
    }// end function

    public function get flag() : uint
    {
        return this._flag;
    }// end function

    public function get mask() : uint
    {
        return this._mask;
    }// end function

    public function get name() : String
    {
        return this._name;
    }// end function

    public function toString() : String
    {
        return "[Sampler name=\"" + this._name + "\", flag=\"" + this._flag + "\", mask=" + this.mask + "]";
    }// end function

}

